#ifndef ARENAROOM_HPP_
#define ARENAROOM_HPP_
#include<memory>
#include<map>
#include<string>

#include "base/Timestamp.hpp"
#include "Baller.hpp"
#include "FoodManager.hpp"
//向前申明
class ArenaRoomMgr;
namespace ProtoMsg
{
    class Dto_ArenaRoomInfo;
    class Dto_ArenaBrief;
    class PerFrameData;
}

using ArenaRoomID = uint32_t;
class ArenaRoom
{
private:
	ArenaRoomID							_id;
	std::string							_name;
	std::map<BallerID,Baller*>			_ballerDict;
	int32_t                             _frameNo;
	FoodManager                         _foodMgr;
	int64_t                             _updateTimems;//毫秒级时间戳
	int64_t								_overTimems;
protected:
	ArenaRoom(ArenaRoomID id,std::string name);
	friend class ArenaRoomMgr;
	void broadcastMsg(ProtoMsg::Packet& packet)
    {
	    for(auto iter : _ballerDict)
        {
	        iter.second->SendPacket(packet);
        }
    }
    bool broadcastFrame();
	int64_t deltaTime(int64_t nowms);
	bool isTimeOver(int64_t delta);
public:
    ~ArenaRoom();
	bool UpdateRoom();
	FoodManager& GetFoodMgr(){return _foodMgr;}

	template<class T>
	void BroadcastMessage(const T& msg,int32_t code = 0)
    {
        ProtoMsg::Packet packet;
        packet.set_name(T::descriptor()->full_name());
        packet.set_content(msg.SerializeAsString());
        packet.set_seq(0);
        packet.set_timestamp(Timestamp::Nowms());
        packet.set_code(code);
        broadcastMsg(packet);
    }

	bool IsExistBaller(BallerID id);
	bool BallerJoin(Baller* baller);
	void BallerExit(Baller* baller);
	uint32_t  NumOfBaller();

	void fillDto_ArenaRoomInfo(ProtoMsg::Dto_ArenaRoomInfo*);
	void fillDto_ArenaBrief(ProtoMsg::Dto_ArenaBrief*);
};
using ArenaRoomPtr = std::shared_ptr<ArenaRoom>;

using RoomDict = std::map<ArenaRoomID,ArenaRoomPtr>;
class ArenaRoomMgr
{
private:
    RoomDict                                _roomDict;
protected:
	static ArenaRoomID					    RoomIDIndex;
	static ArenaRoomMgr*					Instance;

	ArenaRoomMgr(){}
	~ArenaRoomMgr(){}
public:
	static ArenaRoomMgr& 	GetInstance();

	ArenaRoomPtr 			CreateRoom(std::string name,Baller* creator);
	ArenaRoomPtr 			QueryRoom(ArenaRoomID id);
	void                    RemoveRoom(ArenaRoomID id);

	void					BallerExitRoom(Baller* baller);
	void                    BallerExitRoom(BallerID id);

	const RoomDict&         GetRoomDict(){return _roomDict;}
	void					UpdateAllRoom();
};
#endif
